/**
 * 
 */
package info.angelloznicoud.ircdl.bean;

import info.angelloznicoud.ircdl.exception.InvalidDownloadFileName;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

/**
 * Represent a file containing message to bot for downloading file
 * on a xdcc server.
 * 
 * @author ANGELLOZ-NICOUD Sébastien
 *
 * @version 1.0
 */
public class MessageFile {
	
	public static final String DELIMITER = "@";
	
	private static final Logger LOG = Logger.getLogger(MessageFile.class);

	private File file;
	
	private File inProgressDownloadFile;
	
	private String server;
	
	private String channel;
	
	private List<String> lines;
	
	/**
	 * Build a new download file.
	 * 
	 * @param file - path to the file contains XDCC commands
	 * 
	 * @throws IOException
	 * @throws InvalidDownloadFileName
	 */
	public MessageFile(File file) throws IOException, InvalidDownloadFileName {
		this.file  = file;
		this.lines = new ArrayList<String>();
		
		String[] infos = this.file.getName().split("@");
		
		if (infos.length == 2) {
			this.channel = infos[0];
			this.server  = infos[1];
		} else {
			throw new InvalidDownloadFileName(this.file.getAbsolutePath());
		}
		
		this.load();
		this.inProgressDownloadFile = new File(this.file.getAbsolutePath() + ".encours");
	}
	
	/**
	 * Read file line by line.
	 * 
	 * @throws IOException
	 */
	private void load() throws IOException {
		BufferedReader reader = new BufferedReader(new FileReader(this.file));
		String line = null;
		
		LOG.debug("Loading file " + this.file.getAbsolutePath() + ".");
		
		while ((line = reader.readLine()) != null) {
			this.lines.add(line);
		}
		
		reader.close();
	}
	
	/**
	 * Add a line on a particular index.
	 * 
	 * @param line - line to add
	 * @param index - where to add the line
	 */
	public void addLigne(String line, int index) {
		this.lines.add(index, line);
	}
	
	public int getDownloadSize() {
		return this.lines.size();
	}
	
	public String getShortFileName() {
		return this.file.getName();
	}
	
	public String getChannel() {
		return channel;
	}
	
	public String getServer() {
		return server;
	}
	
	public File getInProgressDownloadFile() {
		return inProgressDownloadFile;
	}
	
	/**
	 * Get the next XDCC message from file, create the current progress download file
	 * and save the others XDCC message in the download file.
	 * 
	 * @return The next XDCC message to send, or null if a download is in progress.
	 * May return null if an I/O error occurs.
	 */
	public String getNextFileToDowload() {
		if (downloadInProgress()) {
			LOG.warn("A download is in progress, cannot get next file to download.");
			return null;
		}
		
		if (this.lines.size() > 0) {
			String line = this.lines.get(0);
			try {
				createCurrentDownloadFile(line);
				this.lines.remove(0);
				saveFile();
				return line;
			} catch (IOException e) {
				LOG.error("Cannot get next file to download.", e);
				return null;
			}
		}
		
		return null;
	}
	
	/**
	 * Save the current download file.
	 * 
	 * @throws IOException
	 */
	private void saveFile() throws IOException {
		BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(this.file));
	
		for (String line : this.lines) {
			bufferedWriter.write(line);
			bufferedWriter.newLine();
		}
		
		bufferedWriter.close();
	}
	
	/**
	 * Create progress file.
	 * 
	 * @param content - the XDCC message currently being downloaded
	 * 
	 * @throws IOException if any I/O errors occur.
	 */
	private void createCurrentDownloadFile(String content) throws IOException {
		if (this.inProgressDownloadFile.createNewFile()) {
			BufferedWriter writer = new BufferedWriter(new FileWriter(this.inProgressDownloadFile));
			writer.write(content);
			writer.close();
		} else {
			LOG.warn("In progress download file for " + content + " already exist !");
		}
	}
	
	/**
	 * Delete the current progress file.
	 * 
	 * @return <code>true</code> if the file has been deleted, <code>false</code> otherwise.
	 */
	public boolean deleteCurrendDownloadFile() {
		return this.inProgressDownloadFile.delete();
	}
	
	/**
	 * Return if a download is in progress.
	 * 
	 * @return true or false.
	 */
	public boolean downloadInProgress() {
		return this.inProgressDownloadFile.exists();
	}
}
